#pragma once
#include <array>
#include <cstdint>

class GF256MDS {
public:
    using Bytes16 = std::array<uint8_t, 16>;
    using MDS16x16 = std::array<Bytes16, 16>;

    GF256MDS();

    void mds_map(const Bytes16& input, Bytes16& output) const;
    static void xor_arrays(Bytes16& a, Bytes16& b);

private:
    static constexpr uint8_t ALPHA = 0x03;
    uint8_t gf_mul_table[256][256]{};
    MDS16x16 M;

    uint8_t gf_mul(uint8_t a, uint8_t b) const;
    void init_gf_mul_table();
    MDS16x16 make_mds() const;
};
